package draw;

import graph.Vertex;
import graph.WeightedDirectedGraph;

import java.awt.Color;
import java.awt.Graphics;
import java.util.ArrayList;

import puzzel.Position;
import puzzel.PuzzleColor;

public class PhysicalGraph {

	ArrayList<VertexPoint>	vertices = new ArrayList<VertexPoint>();

	public PhysicalGraph(WeightedDirectedGraph<Position, PuzzleColor> graph) {
		ArrayList<Vertex<Position, PuzzleColor>> tempVertices = graph.getAll();
		for (Vertex<Position, PuzzleColor> vertex : tempVertices) {
			System.out.println("adding");
			vertices.add(new VertexPoint(500+Math.random()*100 - 50,500+Math.random()*100 - 50, vertex.getItem().getColor().toColor(), Integer.toString(vertex.getItem().getNumber())));
		}
		for(int i = 0;i < vertices.size();i++){
			VertexPoint v = vertices.get(i);
			Vertex<Position, PuzzleColor> vOld = tempVertices.get(i);
			for (Vertex<Position, PuzzleColor> vertex : vOld.getNeighbours()){
				if(vertex.equals(null)) break;
				for (int j = 0;j < tempVertices.size();j++) {
					if(tempVertices.get(j).equals(vertex)){
						v.addLink(vertices.get(j),"_", vOld.getCost(vertex.getItem()).toColor());
					}
				}
			}
		}
	}

	public void run() {
		for (VertexPoint vertex : vertices) {
			for (VertexPoint vertex2 : vertices) {
				if (vertex2.equals(vertex))
					break;
				if(distance(vertex,vertex2) < 120){
					vertex.moveAway(vertex2);
					vertex2.moveAway(vertex);
				}
				vertex.runLinks();
			}
		}

	}

	private double distance(VertexPoint first, VertexPoint second) {
		return Math.sqrt(((first.getX() - second.getX()) * (first.getX() - second.getX())) + ((first.getY() - second.getY()) * (first.getY() - second.getY())));
	}
	
	public void draw(Graphics g){
		for (VertexPoint vertex : vertices) {
			vertex.draw(g);
		}
	}

	private class VertexPoint {

		private double	x;
		private double	y;
		private Color	color;
		private String	info;
		private ArrayList<Link> links = new ArrayList<Link>();

		public VertexPoint(double x, double y, Color color, String info) {
			this.x = x;
			this.y = y;
			this.color = color;
			this.info = info;
		}
		
		public void addLink(VertexPoint to,String info,Color color){
			links.add(new Link(to,info,color));
		}
		
		public void moveAway(VertexPoint other){
			x += (x-other.x)/50;
			y += (y-other.y)/50;
		}
		
		public void moveTo(VertexPoint other){
			x -= (x-other.x)/50;
			y -= (y-other.y)/50;
		}

		public double getX() {
			return x;
		}

		public double getY() {
			return y;
		}

		public Color getColor() {
			return color;
		}

		public String getInfo() {
			return info;
		}
		
		public void runLinks(){
			
			
			
			for(Link link : links){
				if(distance(this,link.to) > 190){
					 moveTo(link.to);
				}
				if(distance(this,link.to) < 150){
					moveAway(link.to);
				}
			}
			
			if(x < 0) x += 4;
			if(x > 880) x -= 4;
			if(y < 0 )y += 4;
			if(y > 880)y -= 4;
			//y += Math.random() - 0.499;
			//x += Math.random() - 0.499;
		}
		
		public void draw(Graphics g){
			g.setColor(Color.BLACK);
			g.drawOval((int)x,(int)y,25,25);
			g.drawString(info, (int)x,(int)y);
			g.setColor(color);
			g.fillOval((int)x+2,(int)y+2,21,21);
			
			for(Link link : links){
				g.setColor(link.color);
				g.drawLine((int)x,(int)y,(int)link.to.x,(int)link.to.y);
				double dx = (link.to.x - x)/distance(this,link.to);
				double dy = (link.to.y - y)/distance(this,link.to);
				int[] arrowx = new int[3];
				int[] arrowy = new int[3];
				arrowy[0] = (int)(link.to.y - dy*25);
				arrowx[0] = (int)(link.to.x - dx*25);
				
				arrowx[1] = (int) (arrowx[0]-dy*20);
				arrowy[1] = (int) (arrowy[0]-dx*20);
				
				arrowx[2] = (int) (arrowx[0]+dy*20);
				arrowy[2] = (int) (arrowy[0]+dx*20);
				
				arrowy[0] += dy*30;
				arrowx[0] += dx*30;
				
				g.fillPolygon(arrowx,arrowy,3);
				//g.fillOval((int)(link.to.x - dx*25 - 5),(int)(link.to.y - dy*25 - 5), 10,10);
			}
		}
		
	}

	private class Link {
		String		info;
		VertexPoint	to;
		Color		color;

		public Link(VertexPoint to, String info, Color color) {
			this.info = info;
			this.to = to;
			this.color = color;
		}
	}

}
